package com.ljf.authority.domain.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ljf.authority.domain.base.AuthorityBaseMenuTabulationBaseService;
import com.ljf.authority.domain.repository.*;
import com.ljf.authority.dto.command.*;
import com.ljf.authority.dto.query.*;
import com.ljf.authority.enums.AuthorityBaseMenuPageMethodModeEnum;
import com.ljf.authority.enums.AuthorityBaseMenuTabulationLevelEnum;
import com.ljf.authority.infra.assembler.AuthorityBaseMenuTabulationAssembler;
import com.ljf.authority.model.*;
import com.ljf.authority.vo.*;
import com.ljf.common.domain.entity.KeyCountModel;
import com.ljf.common.domain.service.BasisDomainService;
import com.ljf.common.enums.ActivationEnum;
import com.ljf.common.exception.ServiceException;
import com.ljf.common.utils.CollectionUtil;
import com.ljf.common.utils.StringUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 菜单列表定义  领域服务
 *
 * @author LJF
 * @since 2024-10-17
 */
@Component
@AllArgsConstructor
public class AuthorityBaseMenuTabulationDomainService extends BasisDomainService<AuthorityBaseMenuTabulationRepository, AuthorityBaseMenuTabulationQuery, AuthorityBaseMenuTabulationVO, AuthorityBaseMenuTabulation, AuthorityBaseMenuTabulationCommand> {

    private final AuthorityBaseMenuTabulationAssembler ASSEMBLER = AuthorityBaseMenuTabulationAssembler.INSTANCE;

    private final AuthorityBaseMenuTabulationBaseService baseService;
    private final AuthorityBaseMainMenuDetailRepository mainMenuDetailRepository;
    private final AuthorityBaseMenuPageDetailRepository menuPageDetailRepository;
    private final AuthorityBaseMenuPageDetailRepository pageDetailRepository;
    private final AuthorityBaseButtonDetailRepository buttonDetailRepository;
    private final AuthorityRelPermissionGroupMenuRepository permissionGroupMenuRepository;
    private final AuthorityRelPermissionGroupUserRepository permissionGroupUserRepository;
    private final AuthorityBaseMenuPageMethodRepository pageMethodRepository;
    private final AuthorityRelButtonApiRepository buttonApiRepository;
    private final AuthorityDatPermissionGroupRepository permissionGroupRepository;

    /**
     * 权限树
     *
     * @return
     * @throws ServiceException
     */
    public List<AuthorityBaseMenuTabulationMainMenuVO> tree() throws ServiceException {
        List<AuthorityRelPermissionGroupMenuVO> menuList = queryAuthorityMenu();
        if (CollectionUtil.isEmpty(menuList)) {
            return Collections.emptyList();
        }
        // 有权限的按钮Model
        List<String> menuCodeList = menuList.stream()
                .map(AuthorityRelPermissionGroupMenuVO::getMenuCode).distinct().collect(Collectors.toList());
        List<AuthorityBaseMenuTabulationVO> modelButtonList = queryList(
                menuCodeList, AuthorityBaseMenuTabulationLevelEnum.BUTTON.getCode()
        );
        // 有权限的页面Model
        List<String> pageCodeList = modelButtonList.stream()
                .map(AuthorityBaseMenuTabulationVO::getPCode).distinct().collect(Collectors.toList());
        List<AuthorityBaseMenuTabulationVO> pageModelList = queryList(
                pageCodeList, AuthorityBaseMenuTabulationLevelEnum.MENU_PAGE.getCode()
        );
        // 有权限的菜单分类Model
        List<String> classCodeList = pageModelList.stream()
                .map(AuthorityBaseMenuTabulationVO::getPCode).distinct().collect(Collectors.toList());
        List<AuthorityBaseMenuTabulationVO> classModelList = queryList(
                classCodeList, AuthorityBaseMenuTabulationLevelEnum.MENU_CLASSIFICATION.getCode()
        );
        // 有权限的主菜单Model
        List<String> mainCodeList = classModelList.stream()
                .map(AuthorityBaseMenuTabulationVO::getPCode).distinct().collect(Collectors.toList());
        List<AuthorityBaseMenuTabulationVO> mainModelList = queryList(
                mainCodeList, AuthorityBaseMenuTabulationLevelEnum.MAIN_MENU.getCode()
        );
        // 集合-有权限的菜单Model
        List<AuthorityBaseMenuTabulationVO> modelList = new ArrayList<>(mainModelList);
        modelList.addAll(classModelList);
        modelList.addAll(pageModelList);
        modelList.addAll(modelButtonList);
        // 主菜单信息
        List<AuthorityBaseMainMenuDetailVO> mainMenuList = mainMenuDetailRepository.selectList(
                AuthorityBaseMainMenuDetailQuery.builder().codeList(mainCodeList).build()
        );
        // 页面信息
        List<AuthorityBaseMenuPageDetailVO> menuPageList = menuPageDetailRepository.selectList(
                AuthorityBaseMenuPageDetailQuery.builder().codeList(pageCodeList).build()
        );
        return baseService.buildTree(modelList, mainMenuList, menuPageList);
    }

    /**
     * 权限按钮
     *
     * @param componentUrl
     * @return
     * @throws ServiceException
     */
    public AuthorityBaseMenuTabulationButtonMethodVO button(String componentUrl) throws ServiceException {
        AuthorityBaseMenuPageDetailVO pageDetail = pageDetailRepository.selectOne(
                AuthorityBaseMenuPageDetailQuery.builder().componentUrl(componentUrl).build()
        );
        if (pageDetail == null) {
            throw new ServiceException("权限异常:组件URL地址不存在");
        }
        List<AuthorityBaseMenuTabulationButtonVO> buttonMenu = queryButtonMenu(pageDetail);
        List<String> codeList = new ArrayList<>();
        codeList.add(pageDetail.getCode());
        codeList.addAll(
                buttonMenu.stream().map(AuthorityBaseMenuTabulationVO::getCode).distinct().collect(Collectors.toList())
        );
        List<String> initMethods = new ArrayList<>();
        List<String> destructionMethods = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(codeList)) {
            List<AuthorityBaseMenuPageMethodVO> methodList = pageMethodRepository.selectList(
                    AuthorityBaseMenuPageMethodQuery.builder().codeList(codeList).build()
            );
            baseService.buildMenuMethod(methodList, initMethods, destructionMethods);
        }
        return AuthorityBaseMenuTabulationButtonMethodVO.builder()
                .buttonMenu(buttonMenu)
                .initMethods(initMethods)
                .destructionMethods(destructionMethods)
                .build();
    }

    /**
     * 分页查询
     *
     * @param query
     * @return
     * @throws ServiceException
     */
    @Override
    public Page<AuthorityBaseMenuTabulationVO> query(AuthorityBaseMenuTabulationQuery query) throws ServiceException {
        Page<AuthorityBaseMenuTabulationVO> resultPage = super.query(query);
        if (resultPage != null && CollectionUtil.isNotEmpty(resultPage.getRecords())) {
            // 集合
            Set<String> configuredCodeSet = new HashSet<>();
            // 主菜单明细
            List<String> mainMenuCodeList = resultPage.getRecords().stream()
                    .filter(one -> Objects.equals(one.getLevel(), AuthorityBaseMenuTabulationLevelEnum.MAIN_MENU.getCode()))
                    .map(AuthorityBaseMenuTabulationVO::getCode)
                    .collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(mainMenuCodeList)) {
                List<AuthorityBaseMainMenuDetailVO> mainMenuDetailList = mainMenuDetailRepository.selectList(
                        AuthorityBaseMainMenuDetailQuery.builder().codeList(mainMenuCodeList).build()
                );
                if (CollectionUtil.isNotEmpty(mainMenuDetailList)) {
                    configuredCodeSet.addAll(mainMenuDetailList.stream().map(AuthorityBaseMainMenuDetailVO::getCode).collect(Collectors.toSet()));
                }
            }
            // 页面明细
            List<String> menuPageCodeList = resultPage.getRecords().stream()
                    .filter(one -> Objects.equals(one.getLevel(), AuthorityBaseMenuTabulationLevelEnum.MENU_PAGE.getCode()))
                    .map(AuthorityBaseMenuTabulationVO::getCode)
                    .collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(menuPageCodeList)) {
                List<AuthorityBaseMenuPageDetailVO> menuPageDetailList = menuPageDetailRepository.selectList(
                        AuthorityBaseMenuPageDetailQuery.builder().codeList(menuPageCodeList).build()
                );
                if (CollectionUtil.isNotEmpty(menuPageDetailList)) {
                    configuredCodeSet.addAll(menuPageDetailList.stream().map(AuthorityBaseMenuPageDetailVO::getCode).collect(Collectors.toSet()));
                }
            }
            // 按钮明细
            List<String> buttonCodeList = resultPage.getRecords().stream()
                    .filter(one -> Objects.equals(one.getLevel(), AuthorityBaseMenuTabulationLevelEnum.BUTTON.getCode()))
                    .map(AuthorityBaseMenuTabulationVO::getCode)
                    .collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(buttonCodeList)) {
                List<AuthorityBaseButtonDetailVO> buttonDetailList = buttonDetailRepository.selectList(
                        AuthorityBaseButtonDetailQuery.builder().codeList(buttonCodeList).build()
                );
                if (CollectionUtil.isNotEmpty(buttonDetailList)) {
                    configuredCodeSet.addAll(buttonDetailList.stream().map(AuthorityBaseButtonDetailVO::getCode).collect(Collectors.toSet()));
                }
            }
            // 分组统计关联后端数量
            List<String> codeList = resultPage.getRecords().stream()
                    .map(AuthorityBaseMenuTabulationVO::getCode).distinct().collect(Collectors.toList());
            List<KeyCountModel> keyCountList = buttonApiRepository.countApiCodeGroupByButtonCode(codeList);
            Map<String, Integer> keyCountMap = keyCountList.stream()
                    .collect(Collectors.toMap(KeyCountModel::getKey, KeyCountModel::getNum, Integer::sum));
            // 填充数据
            for (AuthorityBaseMenuTabulationVO result : resultPage.getRecords()) {
                if (!Objects.equals(result.getLevel(), AuthorityBaseMenuTabulationLevelEnum.MENU_CLASSIFICATION.getCode()) && !configuredCodeSet.contains(result.getCode())) {
                    result.setDetailsMissMsg("明细配置缺失");
                }
                result.setBackendCount(keyCountMap.getOrDefault(result.getCode(), 0));
            }
        }
        return resultPage;
    }

    /**
     * 菜单树
     *
     * @return
     * @throws ServiceException
     */
    public List<AuthorityBaseMenuTabulationMainMenuVO> queryMenuTree() throws ServiceException {
        List<AuthorityBaseMenuTabulationVO> modelList = repository.selectList(AuthorityBaseMenuTabulationQuery.builder().build());
        // 主菜单信息
        List<String> mainCodeList = modelList.stream()
                .filter(one -> Objects.equals(one.getLevel(), AuthorityBaseMenuTabulationLevelEnum.MAIN_MENU.getCode()))
                .map(AuthorityBaseMenuTabulationVO::getCode)
                .collect(Collectors.toList());
        List<AuthorityBaseMainMenuDetailVO> mainMenuList = mainMenuDetailRepository.selectList(
                AuthorityBaseMainMenuDetailQuery.builder().codeList(mainCodeList).build()
        );
        // 页面信息
        List<String> pageCodeList = modelList.stream()
                .filter(one -> Objects.equals(one.getLevel(), AuthorityBaseMenuTabulationLevelEnum.MENU_PAGE.getCode()))
                .map(AuthorityBaseMenuTabulationVO::getCode)
                .collect(Collectors.toList());
        List<AuthorityBaseMenuPageDetailVO> menuPageList = menuPageDetailRepository.selectList(
                AuthorityBaseMenuPageDetailQuery.builder().codeList(pageCodeList).build()
        );
        return baseService.buildTree(modelList, mainMenuList, menuPageList);
    }

    /**
     * 新增
     *
     * @param command
     * @return
     * @throws ServiceException
     */
    @Override
    public AuthorityBaseMenuTabulation add(AuthorityBaseMenuTabulationCommand command) throws ServiceException {
        AuthorityBaseMenuTabulationVO pMenuTabulation = null;
        int sort;
        if (StringUtil.isNotEmpty(command.getPCode())) {
            pMenuTabulation = repository.selectOne(
                    AuthorityBaseMenuTabulationQuery.builder().code(command.getPCode()).build()
            );
            sort = repository.count(AuthorityBaseMenuTabulationQuery.builder().pCode(command.getPCode()).build()) + 1;
        }
        else {
            sort = repository.count(AuthorityBaseMenuTabulationQuery.builder().level(AuthorityBaseMenuTabulationLevelEnum.MAIN_MENU.getCode()).build()) + 1;
        }
        AuthorityBaseMenuTabulation model = AuthorityBaseMenuTabulation.builder()
                .code((pMenuTabulation == null ? "" : pMenuTabulation.getCode() + '-') + command.getCode())
                .name((pMenuTabulation == null ? "" : pMenuTabulation.getName() + '-') + command.getLabel())
                .label(command.getLabel())
                .sort(sort)
                .pCode(command.getPCode())
                .level(pMenuTabulation == null ? AuthorityBaseMenuTabulationLevelEnum.MAIN_MENU.getCode() : pMenuTabulation.getLevel() + 1)
                .activation(ActivationEnum.NOT_ACTIVE.getCode())
                .build();
        repository.insert(model);
        return model;
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     * @throws ServiceException
     */
    @Override
    public boolean deleteBatch(List<Long> ids) throws ServiceException {
        List<AuthorityBaseMenuTabulationVO> modelList = repository.selectListByIds(ids);
        List<String> codeList = modelList.stream().map(AuthorityBaseMenuTabulationVO::getCode).distinct().collect(Collectors.toList());
        buttonDetailRepository.physicalDelete(AuthorityBaseButtonDetailQuery.builder().codeList(codeList).build());
        mainMenuDetailRepository.physicalDelete(AuthorityBaseMainMenuDetailQuery.builder().codeList(codeList).build());
        menuPageDetailRepository.physicalDelete(AuthorityBaseMenuPageDetailQuery.builder().codeList(codeList).build());
        pageMethodRepository.physicalDelete(AuthorityBaseMenuPageMethodQuery.builder().codeList(codeList).build());
        buttonApiRepository.physicalDelete(AuthorityRelButtonApiQuery.builder().buttonCodeList(codeList).build());
        permissionGroupMenuRepository.physicalDelete(AuthorityRelPermissionGroupMenuQuery.builder().menuCodeList(codeList).build());
        repository.physicalDeleteBatchByIds(ids);
        List<String> pCodeList = modelList.stream().map(AuthorityBaseMenuTabulationVO::getPCode).distinct().collect(Collectors.toList());
        this.reSortByPCode(pCodeList);
        return true;
    }

    /**
     * 根据ID更新
     *
     * @param command
     * @return
     * @throws ServiceException
     */
    @Override
    public Boolean edit(AuthorityBaseMenuTabulationCommand command) throws ServiceException {
        String code = command.getCode();
        String name = command.getLabel();
        AuthorityBaseMenuTabulationVO model = repository.selectById(command.getId());
        if (StringUtil.isNotEmpty(model.getPCode())) {
            AuthorityBaseMenuTabulationVO pMenuTabulation = repository.selectOne(
                    AuthorityBaseMenuTabulationQuery.builder().code(model.getPCode()).build()
            );
            code = pMenuTabulation.getCode() + '-' + code;
            name = pMenuTabulation.getName() + '-' + name;
        }
        this.execEdit(model.getCode(), code, model.getName(), name, command.getLabel());
        return true;
    }

    /**
     * 根据ID查询菜单树排序
     *
     * @param id
     * @return
     * @throws ServiceException
     */
    public List<AuthorityBaseMenuTabulationVO> querySortById(Long id) throws ServiceException {
        AuthorityBaseMenuTabulationVO model = repository.selectById(id);
        if (model == null) {
            throw new ServiceException("执行异常: 数据不存在, 请刷新后重试");
        }
        if (model.getLevel() == null) {
            throw new ServiceException("数据异常: 层级为空");
        }
        AuthorityBaseMenuTabulationQuery query = AuthorityBaseMenuTabulationQuery.builder()
                .level(model.getLevel())
                .build();
        if (!Objects.equals(model.getLevel(), AuthorityBaseMenuTabulationLevelEnum.MAIN_MENU.getCode())) {
            if (StringUtil.isEmpty(model.getPCode())) {
                throw new ServiceException("数据异常: 上级编码为空");
            }
            query.setPCode(model.getPCode());
        }
        List<AuthorityBaseMenuTabulationVO> resultList = repository.selectList(query);
        resultList.sort(Comparator.comparing(AuthorityBaseMenuTabulationVO::getSort));
        return resultList;
    }

    /**
     * 修改菜单列表排序
     *
     * @param command
     * @throws ServiceException
     */
    public void editSort(AuthorityBaseMenuTabulationSortCommand command) throws ServiceException {
        List<AuthorityBaseMenuTabulationVO> modelList = this.querySortById(command.getId());
        Map<String, Integer> sortMap = new HashMap<>();
        int index = 1;
        for (String code : command.getSortList()) {
            sortMap.put(code, index++);
        }
        List<AuthorityBaseMenuTabulation> needUpdateList = new ArrayList<>();
        for (AuthorityBaseMenuTabulationVO model : modelList) {
            needUpdateList.add(
                    AuthorityBaseMenuTabulation.builder()
                            .id(model.getId())
                            .sort(sortMap.get(model.getCode()))
                            .build()
            );
        }
        repository.updateBatchByIds(needUpdateList);
    }

    /**
     * 根据ID查询菜单树明细
     *
     * @param id
     * @return
     * @throws ServiceException
     */
    public AuthorityBaseMenuTabulationDetailVO queryDetailById(Long id) throws ServiceException {
        AuthorityBaseMenuTabulationVO model = repository.selectById(id);
        AuthorityBaseMenuTabulationDetailVO result = AuthorityBaseMenuTabulationDetailVO.builder()
                .id(model.getId())
                .code(model.getCode())
                .name(model.getName())
                .level(model.getLevel())
                .build();
        if (Objects.equals(AuthorityBaseMenuTabulationLevelEnum.MAIN_MENU.getCode(), result.getLevel())) {
            List<AuthorityBaseMainMenuDetailVO> mainMenuDetailList = mainMenuDetailRepository.selectList(
                    AuthorityBaseMainMenuDetailQuery.builder().code(result.getCode()).build()
            );
            if (CollectionUtil.isNotEmpty(mainMenuDetailList)) {
                result.setPicCode(mainMenuDetailList.get(0).getPicCode());
            }
        }
        if (Objects.equals(AuthorityBaseMenuTabulationLevelEnum.MENU_PAGE.getCode(), result.getLevel())) {
            List<AuthorityBaseMenuPageDetailVO> menuPageDetailList = pageDetailRepository.selectList(
                    AuthorityBaseMenuPageDetailQuery.builder().code(result.getCode()).build()
            );
            if (CollectionUtil.isNotEmpty(menuPageDetailList)) {
                result.setComponentUrl(menuPageDetailList.get(0).getComponentUrl());
            }
        }
        if (Objects.equals(AuthorityBaseMenuTabulationLevelEnum.BUTTON.getCode(), result.getLevel())) {
            List<AuthorityBaseButtonDetailVO> buttonDetailList = buttonDetailRepository.selectList(
                    AuthorityBaseButtonDetailQuery.builder().code(result.getCode()).build()
            );
            if (CollectionUtil.isNotEmpty(buttonDetailList)) {
                result.setClickFunction(buttonDetailList.get(0).getClickFunction());
                result.setWidth(buttonDetailList.get(0).getWidth());
            }
        }
        return result;
    }

    /**
     * 修改菜单列表明细
     *
     * @param command
     * @throws ServiceException
     */
    public void editDetail(AuthorityBaseMenuTabulationDetailCommand command) throws ServiceException {
        AuthorityBaseMenuTabulationVO model = repository.selectById(command.getId());
        if (Objects.equals(AuthorityBaseMenuTabulationLevelEnum.MAIN_MENU.getCode(), model.getLevel())) {
            List<AuthorityBaseMainMenuDetailVO> mainMenuDetailList = mainMenuDetailRepository.selectList(
                    AuthorityBaseMainMenuDetailQuery.builder().code(model.getCode()).build()
            );
            if (CollectionUtil.isEmpty(mainMenuDetailList)) {
                mainMenuDetailRepository.insert(
                        AuthorityBaseMainMenuDetail.builder()
                                .code(model.getCode())
                                .picCode(command.getPicCode() == null ? "" : command.getPicCode())
                                .build()
                );
            }
            else {
                mainMenuDetailRepository.updateById(
                        AuthorityBaseMainMenuDetail.builder()
                                .id(mainMenuDetailList.get(0).getId())
                                .picCode(command.getPicCode() == null ? "" : command.getPicCode())
                                .build()
                );
            }
        }
        else if (Objects.equals(AuthorityBaseMenuTabulationLevelEnum.MENU_PAGE.getCode(), model.getLevel())) {
            List<AuthorityBaseMenuPageDetailVO> menuPageDetailList = pageDetailRepository.selectList(
                    AuthorityBaseMenuPageDetailQuery.builder().code(model.getCode()).build()
            );
            if (CollectionUtil.isEmpty(menuPageDetailList)) {
                pageDetailRepository.insert(
                        AuthorityBaseMenuPageDetail.builder()
                                .code(model.getCode())
                                .componentUrl(command.getComponentUrl() == null ? "" : command.getComponentUrl())
                                .build()
                );
            }
            else {
                pageDetailRepository.updateById(
                        AuthorityBaseMenuPageDetail.builder()
                                .id(menuPageDetailList.get(0).getId())
                                .componentUrl(command.getComponentUrl() == null ? "" : command.getComponentUrl())
                                .build()
                );
            }
        }
        else if (Objects.equals(AuthorityBaseMenuTabulationLevelEnum.BUTTON.getCode(), model.getLevel())) {
            List<AuthorityBaseButtonDetailVO> buttonDetailList = buttonDetailRepository.selectList(
                    AuthorityBaseButtonDetailQuery.builder().code(model.getCode()).build()
            );
            if (CollectionUtil.isEmpty(buttonDetailList)) {
                buttonDetailRepository.insert(
                        AuthorityBaseButtonDetail.builder()
                                .code(model.getCode())
                                .clickFunction(command.getClickFunction() == null ? "" : command.getClickFunction())
                                .width(command.getWidth())
                                .build()
                );
            }
            else {
                buttonDetailRepository.updateById(
                        AuthorityBaseButtonDetail.builder()
                                .id(buttonDetailList.get(0).getId())
                                .clickFunction(command.getClickFunction() == null ? "" : command.getClickFunction())
                                .width(command.getWidth())
                                .build()
                );
            }
        }
    }

    /**
     * 根据ID查询菜单关联后端
     *
     * @param id
     * @return
     * @throws ServiceException
     */
    public AuthorityBaseMenuTabulationBackendVO queryBackendById(Long id) throws ServiceException {
        AuthorityBaseMenuTabulationVO model = repository.selectById(id);
        List<AuthorityRelButtonApiVO> buttonApiList = buttonApiRepository.selectList(
                AuthorityRelButtonApiQuery.builder().buttonCode(model.getCode()).build()
        );
        List<String> backendList = buttonApiList.stream()
                .map(AuthorityRelButtonApiVO::getApiCode).distinct().collect(Collectors.toList());
        return AuthorityBaseMenuTabulationBackendVO.builder()
                .code(model.getCode())
                .name(model.getName())
                .level(model.getLevel())
                .backendList(backendList)
                .build();
    }

    /**
     * 修改菜单列表关联后端
     *
     * @param command
     * @throws ServiceException
     */
    public void editBackend(AuthorityBaseMenuTabulationBackendCommand command) throws ServiceException {
        AuthorityBaseMenuTabulationVO model = repository.selectById(command.getId());
        List<AuthorityRelButtonApiVO> buttonApiList = buttonApiRepository.selectList(
                AuthorityRelButtonApiQuery.builder().buttonCode(model.getCode()).build()
        );
        List<AuthorityRelButtonApi> needInsertApiList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(buttonApiList)) {
            List<Long> needDeleteList = buttonApiList.stream().map(AuthorityRelButtonApiVO::getId).collect(Collectors.toList());
            buttonApiRepository.physicalDeleteBatchByIds(needDeleteList);
        }
        if (CollectionUtil.isNotEmpty(command.getBackendList())) {
            for (String backendCode : command.getBackendList()) {
                needInsertApiList.add(AuthorityRelButtonApi.builder().apiCode(backendCode).buttonCode(model.getCode()).build());
            }
            buttonApiRepository.insertBatch(needInsertApiList);
        }
    }

    /**
     * 根据ID查询菜单按钮方法
     *
     * @param id
     * @return
     * @throws ServiceException
     */
    public AuthorityBaseMenuTabulationMethodVO queryMethodById(Long id) throws ServiceException {
        AuthorityBaseMenuTabulationVO model = repository.selectById(id);
        List<AuthorityBaseMenuPageMethodVO> pageMethodList = pageMethodRepository.selectList(
                AuthorityBaseMenuPageMethodQuery.builder().code(model.getCode()).build()
        );
        List<String> methodList = pageMethodList.stream()
                .map(AuthorityBaseMenuPageMethodVO::getMethod).distinct().collect(Collectors.toList());
        return AuthorityBaseMenuTabulationMethodVO.builder()
                .code(model.getCode())
                .name(model.getName())
                .level(model.getLevel())
                .methodList(methodList)
                .build();
    }

    /**
     * 修改菜单列表按钮方法
     *
     * @param command
     * @throws ServiceException
     */
    public void editMethod(AuthorityBaseMenuTabulationMethodCommand command) throws ServiceException {
        AuthorityBaseMenuTabulationVO model = repository.selectById(command.getId());
        List<AuthorityBaseMenuPageMethodVO> pageMethodList = pageMethodRepository.selectList(
                AuthorityBaseMenuPageMethodQuery.builder().code(model.getCode()).build()
        );
        List<AuthorityBaseMenuPageMethod> needInsertApiList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(pageMethodList)) {
            List<Long> needDeleteList = pageMethodList.stream().map(AuthorityBaseMenuPageMethodVO::getId).collect(Collectors.toList());
            pageMethodRepository.physicalDeleteBatchByIds(needDeleteList);
        }
        if (CollectionUtil.isNotEmpty(command.getMethodList())) {
            for (String method : command.getMethodList()) {
                needInsertApiList.add(
                        AuthorityBaseMenuPageMethod.builder()
                                .code(model.getCode())
                                .method(method)
                                .mode(AuthorityBaseMenuPageMethodModeEnum.INIT_EXEC.getCode())
                                .build()
                );
            }
            pageMethodRepository.insertBatch(needInsertApiList);
        }
    }

    /**
     * 修改菜单列表激活状态
     *
     * @param command
     * @throws ServiceException
     */
    public void editActivation(AuthorityBaseMenuTabulationActivationCommand command) throws ServiceException {
        repository.update(
                AuthorityBaseMenuTabulation.builder().activation(command.getActivation()).build(),
                AuthorityBaseMenuTabulationQuery.builder().ids(command.getIds()).build()
        );
    }

    /**
     * 修改菜单列表关联权限组
     *
     * @param command
     * @throws ServiceException
     */
    public void editPermissionGroup(AuthorityBaseMenuTabulationPermissionGroupCommand command) throws ServiceException {
        AuthorityBaseMenuTabulationVO model = repository.selectById(command.getId());
        List<AuthorityRelPermissionGroupMenuVO> permissionGroupMenuList = permissionGroupMenuRepository.selectList(
                AuthorityRelPermissionGroupMenuQuery.builder().menuCode(model.getCode()).build()
        );
        List<AuthorityRelPermissionGroupMenu> needInsertApiList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(permissionGroupMenuList)) {
            List<Long> needDeleteList = permissionGroupMenuList.stream()
                    .map(AuthorityRelPermissionGroupMenuVO::getId).collect(Collectors.toList());
            permissionGroupMenuRepository.physicalDeleteBatchByIds(needDeleteList);
        }
        if (CollectionUtil.isNotEmpty(command.getPermissionGroupList())) {
            for (String permissionGroupCode : command.getPermissionGroupList()) {
                needInsertApiList.add(
                        AuthorityRelPermissionGroupMenu.builder()
                                .groupCode(permissionGroupCode)
                                .menuCode(model.getCode())
                                .build()
                );
            }
            permissionGroupMenuRepository.insertBatch(needInsertApiList);
        }
    }

    /**
     * 根据ID查询菜单权限组
     *
     * @param id
     * @return
     * @throws ServiceException
     */
    public AuthorityBaseMenuTabulationPermissionGroupVO queryPermissionGroupById(Long id) throws ServiceException {
        AuthorityBaseMenuTabulationVO model = repository.selectById(id);
        List<AuthorityRelPermissionGroupMenuVO> permissionGroupMenuList = permissionGroupMenuRepository.selectList(
                AuthorityRelPermissionGroupMenuQuery.builder().menuCode(model.getCode()).build()
        );
        List<String> groupCodeList = permissionGroupMenuList.stream()
                .map(AuthorityRelPermissionGroupMenuVO::getGroupCode).distinct().collect(Collectors.toList());
        List<AuthorityDatPermissionGroupVO> permissionGroupList = Collections.emptyList();
        if (CollectionUtil.isNotEmpty(groupCodeList)) {
            permissionGroupList = permissionGroupRepository.selectList(AuthorityDatPermissionGroupQuery.builder().codeList(groupCodeList).build());
        }
        return AuthorityBaseMenuTabulationPermissionGroupVO.builder()
                .code(model.getCode())
                .name(model.getName())
                .level(model.getLevel())
                .permissionGroupList(permissionGroupList)
                .build();
    }

    /**
     * 根据上级编辑重新排序
     *
     * @param pCodeList
     * @throws ServiceException
     */
    private void reSortByPCode(List<String> pCodeList) throws ServiceException {
        if (CollectionUtil.isEmpty(pCodeList)) {
            return;
        }
        List<AuthorityBaseMenuTabulationVO> modelList = repository.selectList(
                AuthorityBaseMenuTabulationQuery.builder().pCodeList(pCodeList).build()
        );
        modelList.sort(Comparator.comparing(AuthorityBaseMenuTabulationVO::getPCode).thenComparing(AuthorityBaseMenuTabulationVO::getSort));
        String pCode = null;
        List<AuthorityBaseMenuTabulation> needUpdateModelList = new ArrayList<>();
        int sort = 1;
        for (AuthorityBaseMenuTabulationVO model : modelList) {
            if (!StringUtil.equals(pCode, model.getPCode())) {
                pCode = model.getPCode();
                sort = 1;
            }
            needUpdateModelList.add(AuthorityBaseMenuTabulation.builder().id(model.getId()).sort(sort++).build());
        }
        repository.updateBatchByIds(needUpdateModelList);
    }

    /**
     * 执行更新
     *
     * @param oldCode
     * @param code
     * @param name
     * @param oldName
     * @param label
     * @throws ServiceException
     */
    private void execEdit(String oldCode, String code, String oldName, String name, String label) throws ServiceException {
        // 主数据
        repository.update(
                AuthorityBaseMenuTabulation.builder().code(code).name(name).label(label).build(),
                AuthorityBaseMenuTabulationQuery.builder().code(oldCode).build()
        );
        // 子集
        List<AuthorityBaseMenuTabulation> needUpdateModelList = new ArrayList<>();
        List<AuthorityBaseMenuTabulationVO> childrenModelList = repository.selectList(
                AuthorityBaseMenuTabulationQuery.builder().pCodeRightLike(oldCode).build()
        );
        if (CollectionUtil.isNotEmpty(childrenModelList)) {
            for (AuthorityBaseMenuTabulationVO childrenModel : childrenModelList) {
                String childrenCode = childrenModel.getCode().replace(oldCode, code);
                if (childrenCode.length() > 60) {
                    throw new ServiceException(String.format("校验异常: 子集编码【%s】不能大于60个字符", childrenCode));
                }
                String childrenName = childrenModel.getName().replace(oldName, name);
                if (childrenName.length() > 30) {
                    throw new ServiceException(String.format("校验异常: 子集名称【%s】不能大于30个字符", childrenName));
                }
                needUpdateModelList.add(
                        AuthorityBaseMenuTabulation.builder()
                                .id(childrenModel.getId())
                                .code(childrenCode)
                                .name(childrenName)
                                .pCode(childrenModel.getPCode().replace(oldCode, code))
                                .build()
                );
            }
        }
        if (!Objects.equals(oldCode, code)) {
            // 关联信息-按钮明细
            List<AuthorityBaseButtonDetailVO> buttonDetailList = buttonDetailRepository.selectList(
                    AuthorityBaseButtonDetailQuery.builder().codeRightLike(oldCode).build()
            );
            List<AuthorityBaseButtonDetail> needUpdateButtonDetailList = new ArrayList<>();
            for (AuthorityBaseButtonDetailVO buttonDetail : buttonDetailList) {
                needUpdateButtonDetailList.add(
                        AuthorityBaseButtonDetail.builder()
                                .id(buttonDetail.getId())
                                .code(buttonDetail.getCode().replace(oldCode, code))
                                .build()
                );
            }
            // 关联信息-主菜单明细
            List<AuthorityBaseMainMenuDetailVO> mainMenuDetailList = mainMenuDetailRepository.selectList(
                    AuthorityBaseMainMenuDetailQuery.builder().codeRightLike(oldCode).build()
            );
            List<AuthorityBaseMainMenuDetail> needUpdateMainMenuDetailList = new ArrayList<>();
            for (AuthorityBaseMainMenuDetailVO mainMenuDetail : mainMenuDetailList) {
                needUpdateMainMenuDetailList.add(
                        AuthorityBaseMainMenuDetail.builder()
                                .id(mainMenuDetail.getId())
                                .code(mainMenuDetail.getCode().replace(oldCode, code))
                                .build()
                );
            }
            // 关联信息-页面明细
            List<AuthorityBaseMenuPageDetailVO> menuPageDetailList = menuPageDetailRepository.selectList(
                    AuthorityBaseMenuPageDetailQuery.builder().codeRightLike(oldCode).build()
            );
            List<AuthorityBaseMenuPageDetail> needUpdateMenuPageDetailList = new ArrayList<>();
            for (AuthorityBaseMenuPageDetailVO menuPageDetail : menuPageDetailList) {
                needUpdateMainMenuDetailList.add(
                        AuthorityBaseMainMenuDetail.builder()
                                .id(menuPageDetail.getId())
                                .code(menuPageDetail.getCode().replace(oldCode, code))
                                .build()
                );
            }
            // 关联信息-页面方法
            List<AuthorityBaseMenuPageMethodVO> pageMethodList = pageMethodRepository.selectList(
                    AuthorityBaseMenuPageMethodQuery.builder().codeRightLike(oldCode).build()
            );
            List<AuthorityBaseMenuPageMethod> needUpdatePageMethodList = new ArrayList<>();
            for (AuthorityBaseMenuPageMethodVO pageMethod : pageMethodList) {
                needUpdatePageMethodList.add(
                        AuthorityBaseMenuPageMethod.builder()
                                .id(pageMethod.getId())
                                .code(pageMethod.getCode().replace(oldCode, code))
                                .build()
                );
            }
            // 关联信息-按钮API关联
            List<AuthorityRelButtonApiVO> buttonApiList = buttonApiRepository.selectList(
                    AuthorityRelButtonApiQuery.builder().buttonCodeRightLike(oldCode).build()
            );
            List<AuthorityRelButtonApi> needUpdateButtonApiList = new ArrayList<>();
            for (AuthorityRelButtonApiVO buttonApi : buttonApiList) {
                needUpdateButtonApiList.add(
                        AuthorityRelButtonApi.builder()
                                .id(buttonApi.getId())
                                .buttonCode(buttonApi.getButtonCode().replace(oldCode, code))
                                .build()
                );
            }
            // 关联信息-权限组菜单关联
            List<AuthorityRelPermissionGroupMenuVO> permissionGroupMenuList = permissionGroupMenuRepository.selectList(
                    AuthorityRelPermissionGroupMenuQuery.builder().menuCodeRightLike(oldCode).build()
            );
            List<AuthorityRelPermissionGroupMenu> needUpdatePermissionGroupMenuList = new ArrayList<>();
            for (AuthorityRelPermissionGroupMenuVO permissionGroupMenu : permissionGroupMenuList) {
                needUpdatePermissionGroupMenuList.add(
                        AuthorityRelPermissionGroupMenu.builder()
                                .id(permissionGroupMenu.getId())
                                .menuCode(permissionGroupMenu.getMenuCode().replace(oldCode, code))
                                .build()
                );
            }
            // 更新
            buttonDetailRepository.updateBatchByIds(needUpdateButtonDetailList);
            mainMenuDetailRepository.updateBatchByIds(needUpdateMainMenuDetailList);
            menuPageDetailRepository.updateBatchByIds(needUpdateMenuPageDetailList);
            pageMethodRepository.updateBatchByIds(needUpdatePageMethodList);
            buttonApiRepository.updateBatchByIds(needUpdateButtonApiList);
            permissionGroupMenuRepository.updateBatchByIds(needUpdatePermissionGroupMenuList);
        }
        // 更新
        repository.updateBatchByIds(needUpdateModelList);

    }

    /**
     * 查询按钮菜单
     *
     * @param pageDetail
     * @return
     * @throws ServiceException
     */
    private List<AuthorityBaseMenuTabulationButtonVO> queryButtonMenu(AuthorityBaseMenuPageDetailVO pageDetail) throws ServiceException {
        List<AuthorityRelPermissionGroupMenuVO> menuList = queryAuthorityMenu();
        List<String> menuCodeList = menuList.stream()
                .map(AuthorityRelPermissionGroupMenuVO::getMenuCode).distinct().collect(Collectors.toList());
        List<AuthorityBaseMenuTabulationVO> buttonMenuList = repository.selectList(
                AuthorityBaseMenuTabulationQuery.builder().pCode(pageDetail.getCode()).codeList(menuCodeList).activation(ActivationEnum.ACTIVATED.getCode()).build()
        );
        List<AuthorityBaseMenuTabulationButtonVO> resultList = ASSEMBLER.toButtonVO(buttonMenuList);
        if (CollectionUtil.isNotEmpty(resultList)) {
            List<String> buttonCodeList = resultList.stream()
                    .map(AuthorityBaseMenuTabulationVO::getCode)
                    .collect(Collectors.toList());
            List<AuthorityBaseButtonDetailVO> buttonDetailList = buttonDetailRepository.selectList(
                    AuthorityBaseButtonDetailQuery.builder().codeList(buttonCodeList).build()
            );
            baseService.buildButton(resultList, buttonDetailList);
        }
        return resultList;
    }

    /**
     * 查询列表
     *
     * @param codeList
     * @param level
     * @return
     * @throws ServiceException
     */
    private List<AuthorityBaseMenuTabulationVO> queryList(List<String> codeList, Integer level) throws ServiceException {
        return repository.selectList(
                AuthorityBaseMenuTabulationQuery.builder()
                        .codeList(codeList)
                        .level(level)
                        .activation(ActivationEnum.ACTIVATED.getCode())
                        .build()
        );
    }

    /**
     * 获取权限菜单
     *
     * @return
     * @throws ServiceException
     */
    private List<AuthorityRelPermissionGroupMenuVO> queryAuthorityMenu() throws ServiceException {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        String user = request.getHeader("user");
        if (StringUtil.isEmpty(user)) {
            throw new ServiceException("权限异常:获取用户失败");
        }
        List<AuthorityRelPermissionGroupUserVO> permissionGroupUserList = permissionGroupUserRepository.selectList(
                AuthorityRelPermissionGroupUserQuery.builder().user(user).build()
        );
        if (CollectionUtil.isEmpty(permissionGroupUserList)) {
            throw new ServiceException("权限异常:您未授权，请联系管理员");
        }
        List<String> groupCodeList = permissionGroupUserList.stream()
                        .map(AuthorityRelPermissionGroupUserVO::getGroupCode).distinct().collect(Collectors.toList());
        return permissionGroupMenuRepository.selectList(
                AuthorityRelPermissionGroupMenuQuery.builder().groupCodeList(groupCodeList).build()
        );
    }

}
